home *** CD-ROM | disk | FTP | other *** search
- // **********************************************
- // File: DISPLAY.CPP
- // The display module
-
- #include "muzika.h"
- #include <stdio.h>
- #include <string.h>
- #include <values.h>
-
- HWND hEditWnd; // The edit window handle
- HCURSOR hEditCursor; // The handle of the edit window cursor
- int currStaffHeight; // Height of the currently displayed staff
- STAFFLOC staffLoc; // Current staff location within multiple
- int staffX, staffY; // Coordinates of the current staff
- int scoreMultiplicity, scoreStaves; // Parameters for the score display
- int scoreFirstStaff, scoreFirstPart; // Parameters for the score display
-
- // **********************************************
- // Following are the Edit window functions
-
- // **********************************************
- // RegisterEditClass registers the Edit window class
- // during the first-instance initialization (called by
- // InitMainFirst in MAIN.CPP).
-
- void RegisterEditClass(HANDLE hInstance)
- {
- WNDCLASS wc;
-
- // Register the edit window class
- wc.lpszClassName = "MUZIKA_edit";
- wc.hInstance = hInstance;
- wc.lpfnWndProc = EditWindowProc;
- wc.hCursor = NULL;
- wc.hIcon = NULL;
- wc.lpszMenuName = NULL;
- wc.hbrBackground = COLOR_APPWORKSPACE+1;
- wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- RegisterClass(&wc);
- }
-
- // **********************************************
- // CreateEditWindow creates and displays an edit window
- // (this is the window where the edited score is displayed).
-
- void CreateEditWindow(HANDLE hInstance)
- {
- // Get the main window extents
- RECT mainExt;
- GetClientRect(hMainWnd, &mainExt);
-
- // Create and display the edit window
- hEditWnd = CreateWindow("MUZIKA_edit",
- NULL,
- WS_CHILDWINDOW | WS_VSCROLL,
- 73, 37,
- mainExt.right-72, mainExt.bottom-36,
- hMainWnd,
- NULL,
- hInstance,
- NULL);
- ShowScrollBar(hEditWnd, SB_VERT, FALSE);
- ShowWindow(hEditWnd, SW_SHOWNA);
-
- // Set the initial cursor
- hEditCursor = LoadCursor(NULL, IDC_ARROW);
- }
-
- // **********************************************
- // EditWindowProc is the edit window procedure, which responds to messages
- // intended for the edit window. The messages processed are described within.
-
- long FAR PASCAL EditWindowProc(
- HWND hWnd, unsigned message, WORD wParam, LONG lParam)
- {
- static int Xfrom, Xto, Y, Yfrom, Yto;
- static enum {NEWCONTINUOUS, MOVEOBJECT, MOVESTAFF} capture;
-
- // Check message type
- switch(message) {
- case WM_PAINT:
- // Process a WM_PAINT message, indicating that the window
- // should be repainted.
- PaintEditWindow(hWnd);
- break;
-
- case WM_MOUSEMOVE:
- // Process a WM_MOUSEMOVE message, indicating that the cursor
- // has moved in the edit window region; the cursor shape should
- // be changed to the current symbol shape.
- SetCursor(hEditCursor);
- break;
-
- case WM_LBUTTONDOWN:
- // Process a WM_LBUTTONDOWN message, indicating that the user
- // has clicked the left mouse button. According to what the
- // current edit symbol is, an editing action is performed.
- if (melodyExists)
- if (!scoreDisplay)
- switch (GetActiveSymbol()) {
- case PENCIL:
- // The current symbol is the pencil on a staff:
- // insert a new staff at the current position
- NewMultipleStaff(MAKEPOINT(lParam).y);
- break;
-
- case ERASER:
- // The current symbol is the eraser:
- // erase the symbols at the current cursor position
- DeleteMusicalObject(MAKEPOINT(lParam).x, MAKEPOINT(lParam).y);
- break;
-
- case HAND:
- // The current symbol is the hand:
- // capture the mouse until the left button is released,
- // then move the objects to their new place.
- Xfrom = MAKEPOINT(lParam).x;
- Yfrom = MAKEPOINT(lParam).y;
- SetCapture(hEditWnd);
- capture = MOVEOBJECT;
- break;
-
- default:
- // The current symbol is one of the musical object symbols:
- // insert the appropriate object at the current position
- SymbolClass *currentSymbol = GetCurrentSymbol();
- switch (currentSymbol->GetType()) {
- case POINTOBJECT:
- // The symbol corresponds to a point object:
- // just insert the object in the staff
- NewPointObject(currentSymbol,
- MAKEPOINT(lParam).x, MAKEPOINT(lParam).y);
- break;
-
- case CONTINUOUSOBJECT:
- // The symbol corresponds to a continuous object:
- // capture the mouse until the left button is released,
- // then create the object between its two extents.
- Xfrom = MAKEPOINT(lParam).x;
- Y = MAKEPOINT(lParam).y;
- SetCapture(hEditWnd);
- capture = NEWCONTINUOUS;
- break;
- }
- }
- else
- // No editing is allowed on a score display
- MessageBox(hWnd, "Cannot edit a score display", NULL,
- MB_ICONSTOP | MB_OK);
- break;
-
- case WM_LBUTTONUP:
- // Process a WM_LBUTTONUP message, indicating that the
- // left mouse button has been released. In case the mouse cursor
- // was captured (presumably because of an operation that required
- // two points to operate), release the capture and complete
- // the operation.
- if (GetCapture() == hEditWnd) {
- switch (capture) {
- case NEWCONTINUOUS:
- // The capture was due to insertion of a continuous object:
- // insert a new continuous object between the two points
- Xto = MAKEPOINT(lParam).x;
- if (Xto < Xfrom) {
- int temp = Xto;
- Xto = Xfrom;
- Xfrom = temp;
- }
- if (Xto != Xfrom)
- NewContinuousObject(GetCurrentSymbol(), Xfrom, Xto, Y);
- break;
-
- case MOVEOBJECT:
- // The capture was due to an object moving operation:
- // move a musical object to its new place
- Xto = MAKEPOINT(lParam).x;
- Yto = MAKEPOINT(lParam).y;
- MoveMusicalObject(Xfrom, Yfrom, Xto, Yto);
- break;
-
- case MOVESTAFF:
- // The capture was due to a staff moving operation:
- // move the staff to its new place
- Yto = MAKEPOINT(lParam).y;
- MoveStaff(Yfrom, Yto);
- break;
- }
- ReleaseCapture();
- }
- break;
-
- case WM_LBUTTONDBLCLK:
- // Process a WM_LBUTTONDBLCLK, indicating that the user has
- // double-clicked the left mouse button. According to what the
- // current edit symbol is, an editing action is performed.
- if (melodyExists)
- if (!scoreDisplay)
- switch(GetActiveSymbol()) {
- case ERASER:
- // The current symbol is the eraser:
- // erase the multiple staff
- DeleteMultipleStaff(MAKEPOINT(lParam).y);
- break;
-
- case HAND:
- // The current symbol is the hand:
- // capture the mouse until the left button is released,
- // then move the staff to its new place.
- Yfrom = MAKEPOINT(lParam).y;
- SetCapture(hEditWnd);
- capture = MOVESTAFF;
- break;
- }
- break;
-
- case WM_VSCROLL:
- // Process a WM_VSCROLL message, indicating that the user
- // has clicked on the scroll bar. The screen should be updated
- // according to the new position of the scroll bar thumb.
- unsigned newY = GetScrollPos(hEditWnd, SB_VERT);
- int minScroll, maxScroll;
- GetScrollRange(hEditWnd, SB_VERT, &minScroll, &maxScroll);
- RECT editRect;
- GetClientRect(hEditWnd, &editRect);
-
- // Process the various possibilities of the scroll bar notification
- switch (wParam) {
- case SB_BOTTOM:
- SetScrollPos(hEditWnd, SB_VERT, maxScroll, TRUE);
- break;
-
- case SB_LINEDOWN:
- SetScrollPos(hEditWnd, SB_VERT,
- newY+(scoreDisplay ? 1 : pixelsPerStaff), TRUE);
- break;
-
- case SB_LINEUP:
- SetScrollPos(hEditWnd, SB_VERT,
- newY-(scoreDisplay ? 1 : pixelsPerStaff), TRUE);
- break;
-
- case SB_PAGEDOWN:
- SetScrollPos(hEditWnd, SB_VERT,
- newY+editRect.bottom/(scoreDisplay ? pixelsPerStaff : 1), TRUE);
- break;
-
- case SB_PAGEUP:
- SetScrollPos(hEditWnd, SB_VERT,
- newY-editRect.bottom/(scoreDisplay ? pixelsPerStaff : 1), TRUE);
- break;
-
- case SB_THUMBPOSITION:
- SetScrollPos(hEditWnd, SB_VERT, LOWORD(lParam), TRUE);
- break;
-
- case SB_TOP:
- SetScrollPos(hEditWnd, SB_VERT, 0, TRUE);
- break;
-
- case SB_ENDSCROLL:
- if (scoreDisplay)
- scoreFirstStaff = newY;
- else
- ((Part *) &melody.part[displayedPart])->SetPartY(newY);
- InvalidateRect(hEditWnd, NULL, TRUE);
- break;
- }
- break;
-
- default:
- // Unrecognized message: just let Windows take care of it.
- return DefWindowProc(hWnd, message, wParam, lParam);
- }
-
- return 0L;
- }
-
- // **********************************************
- // PaintEditWindow is the edit window painting function,
- // activated whenever the edit window receives a WM_PAINT message.
- // It redraws the edit window, including staves and objects.
-
- void PaintEditWindow(HWND hWnd)
- {
- PAINTSTRUCT ps;
- HDC hDC;
-
- // Obtain a display context
- hDC = BeginPaint(hWnd, &ps);
-
- // Draw the page according to the current settings
- if (melodyExists) {
- if (!scoreDisplay) {
- // Display a single part
- Part &p = *((Part *) &melody.part[displayedPart]);
- int firstStaff = 0, lastStaff = 0;
-
- // Display the page
- for (int index = 0; index < p.staff.number(); ++index) {
- int firstY, lastY;
- if (index % p.multiplicity() == 0) {
- firstY = -1;
- lastY = MAXINT-24;
- }
- Staff &s = *((Staff *) &p.staff[index]);
-
- // Draw the staff itself
- if (s.Draw(hDC, p.GetPartY(), TRUE)) {
- if (!firstStaff) firstStaff = index+p.multiplicity();
- lastStaff = index+p.multiplicity();
- staffX = s.X();
- staffY = s.Y()-p.GetPartY();
-
- // Check whether first or last staff in a group
- staffLoc = MIDSTAFF;
- if (index % p.multiplicity() == 0) {
- firstY = staffY;
- staffLoc = FIRSTSTAFF;
- }
- if ((index+1) % p.multiplicity() == 0) {
- lastY = staffY;
- staffLoc = LASTSTAFF;
- }
- if (p.multiplicity() == 1)
- staffLoc = SINGLESTAFF;
- currStaffHeight = (index+1 < p.staff.number()) ?
- ((Staff *) &p.staff[index+1])->Y()-s.Y() : pixelsPerStaff;
-
- // Draw the point objects inside the staff
- IndexedList &pointList = s.pointObject;
- for (int i = 0; i < pointList.number(); ++i)
- ((PointObject *) &pointList[i])->Draw(hDC);
-
- // Draw the continuous objects inside the staff
- IndexedList &contList = s.continuousObject;
- for (i = 0; i < contList.number(); ++i)
- ((ContinuousObject *) &contList[i])->Draw(hDC);
- }
-
- // Check if the multiple staff is complete
- if ((index+1)%p.multiplicity() == 0) {
- if (firstY != -1 || lastY != MAXINT-24) {
- // Draw the connecting lines of a multiple staff
- MoveTo(hDC, s.X(), firstY);
- LineTo(hDC, s.X(), lastY+24);
- MoveTo(hDC, s.X()+s.width()-1, firstY);
- LineTo(hDC, s.X()+s.width()-1, lastY+24);
- }
-
- // Show the marked block
- int i = index/p.multiplicity()*p.multiplicity();
- if (i >= markBeginStaff && i <= markEndStaff) {
- int markFrom, markTo;
- if (i == markBeginStaff)
- markFrom = markBeginX-pixelsPerObject/2;
- if (i > markBeginStaff)
- markFrom = 0;
- if (i == markEndStaff)
- markTo = markEndX+pixelsPerObject/2;
- if (i < markEndStaff)
- markTo = s.width();
- PatBlt(hDC, markFrom+s.X(),
- ((Staff *) &p.staff[i])->Y()-p.GetPartY(),
- markTo-markFrom, s.Y()+25-((Staff *) &p.staff[i])->Y(),
- DSTINVERT);
- }
- }
- }
-
- // Display the status information
- char strnum[15];
- HDC hStatusDC = GetDC(hMainWnd);
- HBRUSH hBrush, hOldBrush;
- hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
- hOldBrush = SelectObject(hStatusDC, hBrush);
- Rectangle(hStatusDC, 108, -1, GetSystemMetrics(SM_CXSCREEN), 37);
- SetBkColor(hStatusDC, GetSysColor(COLOR_WINDOW));
- SetTextAlign(hStatusDC, TA_UPDATECP);
- MoveTo(hStatusDC, 110, 2);
- TextOut(hStatusDC, 0, 0, "Current part: ", 14);
- TextOut(hStatusDC, 0, 0, p.name(), strlen(p.name()));
- TextOut(hStatusDC, 0, 0, ", Staves ", 9);
- sprintf(strnum, "%d-%d",
- firstStaff/p.multiplicity(), lastStaff/p.multiplicity());
- TextOut(hStatusDC, 0, 0, strnum, strlen(strnum));
- SelectObject(hStatusDC, hOldBrush);
- DeleteObject(hBrush);
- ReleaseDC(hMainWnd, hStatusDC);
- }
- else {
- // Display score
- int line = 0;
- int staffLeftX = 32;
- int staffRightX = 32+melody.GetStaffWidth();
- BOOL screenFull = FALSE;
-
- for (int scoreIndex = scoreFirstStaff;
- scoreIndex < scoreStaves && !screenFull; ++scoreIndex) {
- // Draw a multiple staff
- for (int partIndex = scoreFirstPart; partIndex < melody.part.number();
- ++partIndex) {
- Part &p = *((Part *) &melody.part[partIndex]);
- for (int staffIndex = scoreIndex*p.multiplicity();
- staffIndex < (scoreIndex+1)*p.multiplicity(); ++staffIndex) {
- // Draw a single staff
- Staff &s = *((Staff *) &p.staff[staffIndex]);
- int tempY = s.Y();
- s.Y() = line += pixelsPerStaff;
- screenFull = !s.Draw(hDC, 0, TRUE);
- staffX = staffLeftX;
- staffY = line;
-
- // Draw the point objects inside the staff
- IndexedList &pointList = s.pointObject;
- for (int i = 0; i < pointList.number(); ++i)
- ((PointObject *) &pointList[i])->Draw(hDC);
-
- // Draw the continuous objects inside the staff
- IndexedList &contList = s.continuousObject;
- for (i = 0; i < contList.number(); ++i)
- ((ContinuousObject *) &contList[i])->Draw(hDC);
-
- s.Y() = tempY;
- }
- }
-
- // Draw the connecting lines of the score multiple staff
- MoveTo(hDC, staffLeftX, line-(scoreMultiplicity-1)*pixelsPerStaff);
- LineTo(hDC, staffLeftX, line+24);
- MoveTo(hDC, staffRightX, line-(scoreMultiplicity-1)*pixelsPerStaff);
- LineTo(hDC, staffRightX, line+24);
- }
-
- // Display the status information
- char strnum[15];
- HDC hStatusDC = GetDC(hMainWnd);
- HBRUSH hBrush, hOldBrush;
- hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
- hOldBrush = SelectObject(hStatusDC, hBrush);
- Rectangle(hStatusDC, 108, -1, GetSystemMetrics(SM_CXSCREEN), 37);
- SetBkColor(hStatusDC, GetSysColor(COLOR_WINDOW));
- SetTextAlign(hStatusDC, TA_UPDATECP);
- MoveTo(hStatusDC, 110, 2);
- TextOut(hStatusDC, 0, 0, "Score display, Staff ", 21);
- sprintf(strnum, "%d", scoreFirstStaff+1);
- TextOut(hStatusDC, 0, 0, strnum, strlen(strnum));
- SelectObject(hStatusDC, hOldBrush);
- DeleteObject(hBrush);
- ReleaseDC(hMainWnd, hStatusDC);
- }
- }
-
- EndPaint(hWnd, &ps);
- }
-
- // **********************************************
- // Staff::Draw is the Staff class's Draw function,
- // which draws a staff in a display context, returning TRUE
- // if the staff was not entirely clipped.
-
- BOOL Staff :: Draw(HDC hDC, int editYMin, BOOL clip)
- {
- int line = Y();
- RECT staffRect = {0, line-editYMin, melody.GetStaffWidth(), line-editYMin+24};
- RECT windowRect, dummyRect;
-
- // Check whether staff is within screen range
- if (clip) GetClientRect(hEditWnd, &windowRect);
- if (!clip || IntersectRect(&dummyRect, &staffRect, &windowRect)) {
- // Either no clip checking or the staff is within clipping boundaries:
- // draw the staff lines
- for (; line < Y()+5*6; line += 6 ) {
- MoveTo(hDC, X(), line-editYMin);
- LineTo(hDC, X()+width(), line-editYMin);
- }
- return TRUE;
- }
-
- return FALSE;
- }
-